"""
Grid search optimizer for strategy parameters with simple sample-split validation
"""
from typing import Dict, Any, List, Tuple
import itertools
import pandas as pd
from .backtester import run_backtest, compute_metrics


def grid_search(df: pd.DataFrame, param_grid: Dict[str, List[Any]], initial_capital: float = 1_000_000.0, split_date: str = None) -> List[Dict[str, Any]]:
    """遍历参数组合，返回按样本外年化收益排序的结果列表
    split_date: 若提供，则在此日期前为训练（用于选参）, 之后为样本外验证
    """
    keys = list(param_grid.keys())
    combos = list(itertools.product(*(param_grid[k] for k in keys)))
    results = []
    if split_date:
        split_date = pd.to_datetime(split_date)
        train_df = df[pd.to_datetime(df['日期']) <= split_date].copy()
        test_df = df[pd.to_datetime(df['日期']) > split_date].copy()
    else:
        train_df = df.copy()
        test_df = None

    for comb in combos:
        params = dict(zip(keys, comb))
        bt = run_backtest(train_df, params, initial_capital)
        metrics = compute_metrics(bt['equity_curve'], bt['trades'], initial_capital)
        oos_metrics = None
        if test_df is not None:
            bt_oos = run_backtest(test_df, params, initial_capital)
            oos_metrics = compute_metrics(bt_oos['equity_curve'], bt_oos['trades'], initial_capital)

        results.append({'params': params, 'train_metrics': metrics, 'oos_metrics': oos_metrics})

    # sort by oos annualized return if present else train
    def _key(x):
        if x['oos_metrics'] is not None:
            return x['oos_metrics']['annualized_return']
        return x['train_metrics']['annualized_return']

    results = sorted(results, key=_key, reverse=True)
    return results
